// Copyright (c) 2011 Blue Onion Software, All rights reserved
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;

namespace BlueOnionSoftware.Bloget
{
    [Designer(typeof (BlogetCategoryDesigner))]
    public class BlogetCategory : Bloget
    {
        private ITemplate _categoryTemplate;

        [Browsable(false)]
        [Description("Category template")]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof (CategoryContainerControl))]
        public ITemplate CategoryTemplate
        {
            get { return _categoryTemplate; }
            set { _categoryTemplate = value; }
        }

        protected override void CreateChildControls()
        {
            ShowCategories();
            base.CreateChildControls();
        }

        private void ShowCategories()
        {
            if (_categoryTemplate == null)
            {
                Controls.Add(new LiteralControl(@"<ul class=""bloget-category-list"">"));
            }
            var linkMode = (Mode == Mode.Index) ? Mode.Index : Mode.Blog;
            var allCategory = new Category {Name = "All", Id = -1, Count = Blog.AllPostsCount};
            CategoryEntry(linkMode, allCategory);
            foreach (var category in Blog.Categories.Sorted())
            {
                CategoryEntry(linkMode, category);
            }
            if (_categoryTemplate == null)
            {
                Controls.Add(new LiteralControl("</ul>" + Environment.NewLine));
            }
        }

        private void CategoryEntry(Mode linkMode, Category category)
        {
            if (_categoryTemplate != null)
            {
                var categoryContainer = new CategoryContainerControl(this, Blog, category);
                _categoryTemplate.InstantiateIn(categoryContainer);
                Controls.Add(categoryContainer);
            }
            else
            {
                Controls.Add(new LiteralControl("<li>"));
                const string format = "{0} ({1})";
                var link = new HyperLink
                {
                    Text = string.Format(CultureInfo.CurrentCulture, format, category.Name, category.Count),
                    NavigateUrl = BuildQueryString(linkMode, null, 0, category, null, DateTime.MinValue, null)
                };
                Controls.Add(link);
                Controls.Add(new LiteralControl("</li>" + Environment.NewLine));
            }
        }
    }

    internal class BlogetCategoryDesigner : ControlDesigner
    {
        [SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods")]
        public override void Initialize(IComponent component)
        {
            base.Initialize(component);
            SetViewFlags(ViewFlags.TemplateEditing, true);
        }

        public override string GetDesignTimeHtml()
        {
            return "<span>Sample Category</span>";
        }

        public override bool AllowResize
        {
            get { return true; }
        }

        [SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods")]
        public override TemplateGroupCollection TemplateGroups
        {
            get
            {
                var collection = new TemplateGroupCollection();

                var control = (Bloget) Component;
                var group = new TemplateGroup("Bloget");

                var template = new TemplateDefinition(this, "CategoryTemplate", control, "CategoryTemplate", true);
                group.AddTemplateDefinition(template);

                collection.Add(group);
                return collection;
            }
        }
    }

    /// <summary>
    /// CategoryContainerControl defines what can be referenced in the Category template
    /// </summary>
    public class CategoryContainerControl : BlogContainerControl
    {
        private readonly Category _category;

        public CategoryContainerControl(Bloget bloget, Blog blog, Category category)
            : base(bloget, blog)
        {
            _category = category;
        }

        public string CategoryName
        {
            get { return _category.Name; }
        }

        public int CategoryId
        {
            get { return _category.Id; }
        }

        public int CategoryCount
        {
            get { return _category.Count; }
        }
    }
}